//
//  LBWebViewController.m
//
//
//  Created by LINAICAI on 2018/1/12.
//  Copyright © 2018年 李柰财. All rights reserved.
//

#import "LBWebViewController.h"
#import <Masonry.h>
#import <LBTokenStore.h>

NS_ASSUME_NONNULL_BEGIN
@interface LBWebViewController ()<WKNavigationDelegate,WKScriptMessageHandler,WKUIDelegate>
@property (nonatomic , copy)NSString *html;
@property (nonatomic , copy)NSString *url;
@property (nonatomic , copy)NSString *token;
@property (nonatomic , strong)WKWebView *webView;
@property (nonatomic , strong)UIButton *backButton;
@property (nonatomic , strong)NSMutableArray<JavaScriptAction *> *methods;
@property (nonatomic , copy)Handler handler;
@property (nonatomic , strong)UIProgressView *progress;
@end
NS_ASSUME_NONNULL_END
@implementation LBWebViewController
#pragma mark- 构造方法
///主要用于JS交互的
- (instancetype)initUrl:(NSString *)url token:(NSString *)token
{
    return [self initTitle:nil url:url token:token];
}
///主要用于非JS交互的
- (instancetype)initTitle:(NSString *)title url:(NSString *)url
{
    return [self initTitle:title url:url token:nil];
}
///全参数构造方法
- (instancetype)initTitle:(NSString *)title url:(NSString *)url token:(NSString *)token
{
    self = [super initWithNibName:nil bundle:nil];
    if (self) {
        self.navigationItem.title = title;
        self.url = url;
        self.token = token;
    }
    return self;
}

///单独加载html内容并设置标题
- (instancetype)initWithHtml:(NSString *)html title:(NSString *)title
{
    self = [self initTitle:title url:nil token:nil];
    if (self) {
        self.html = html;
    }
    return self;
}
///单独加载html内容
- (instancetype)initWithHtml:(NSString *)html
{
    return  [self initWithHtml:html title:nil];
}
#pragma mark- 懒加载的属性
- (UIButton *)backButton {
    if (!_backButton) {
        _backButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [_backButton setImage:[UIImage imageNamed:@"LBBaseController.bundle/back"] forState:UIControlStateNormal];
        _backButton.frame = CGRectMake(0, 0, 38, 45);
        [_backButton addTarget:self action:@selector(turnBack:) forControlEvents:UIControlEventTouchUpInside];
        [_backButton setImageEdgeInsets:UIEdgeInsetsMake(0, -35, 0, 0)];
    }
    return _backButton;
}

- (UIProgressView *)progress
{
    if (_progress == nil)
    {
        _progress = [[UIProgressView alloc]initWithFrame:CGRectZero];
        _progress.tintColor = [UIColor whiteColor];
        _progress.trackImage = [[UIImage imageNamed:@"LBBaseController.bundle/lb_bar_bg.png"]resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeStretch];
        
    }
    return _progress;
}

- (WKWebView *)webView{
    if (_webView == nil) {
        _webView = [[WKWebView alloc]initWithFrame:CGRectZero];
        _webView.navigationDelegate = self;
        _webView.UIDelegate = self;
        _webView.userInteractionEnabled = YES;
        _webView.opaque = NO;
        _webView.backgroundColor = [UIColor whiteColor];
        _webView.scrollView.showsHorizontalScrollIndicator = NO;
        _webView.scrollView.showsVerticalScrollIndicator = NO;
    }
    return _webView;
}
- (NSMutableArray *)methods{
    if (_methods == nil) {
        _methods = [NSMutableArray<JavaScriptAction *> new];
    }
    return _methods;
}
- (void)addAction:(JavaScriptAction *)action{
    [self.methods addObject:action];
}
- (void)reloadWebView{
    [self.webView reload];
    [self.webView reloadFromOrigin];
}
- (void)loadData{
    if (self.html && self.html.length) {
        [self.webView loadHTMLString:self.html baseURL:nil];
    }
    else{
        ///如果有token,才添加token到url
        if (self.token && self.token.length) {
            if (self.url && [self.url containsString:@"?"]) {
                self.url = [[self.url stringByAppendingString:@"&token="] stringByAppendingString:self.token];
            }
            else{
                self.url = [[self.url stringByAppendingString:@"?token="] stringByAppendingString:self.token];
            }
            
        }
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:self.url]];
        [self.webView loadRequest:request];
    }
    
    
    
    
}
- (void)initView{
    [self.view addSubview:self.webView];
    [self.webView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self.view);
    }];
    [self.view addSubview:self.progress];
    [self.progress mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.top.right.equalTo(self.view);
        make.height.mas_equalTo(3);
    }];
    
}
#pragma mark- 生命周期


- (void)viewDidLoad {
    [super viewDidLoad];
    ///界面
    [self initView];
    ///加载数据
    [self loadData];
    ///加载注册JS方法
    [self registerJavaScript];
    ///监听
    [self.webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:NULL];
    [self.webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];
    ///返回按钮
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.backButton];
    
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
///OC调JS
- (void)evaluateJavaScript:(NSString *)javaScriptString{
    [self.webView evaluateJavaScript:javaScriptString completionHandler:nil];
}
- (void)registerJavaScript{
    ///OC注册供JS调用的方法
    for (JavaScriptAction *action in self.methods) {
        [[self.webView configuration].userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:action.name];
    }
    
}
- (void)turnBack:(UIButton *)button {
    if ([button isEqual:self.backButton]) {
        if (self.webView.canGoBack) {
            [self.webView goBack];
        }
        else {
            [self.navigationController popViewControllerAnimated:YES];
        }
    }
    else {
        [self.navigationController popViewControllerAnimated:YES];
    }
}

#pragma mark- UIDelegate
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:webView.title message:message preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        completionHandler();
    }]];
    [self presentViewController:alert animated:YES completion:nil];
}
#pragma mark- WKNavigationDelegate
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView API_AVAILABLE(macosx(10.11), ios(9.0)){
    NSLog(@"webViewWebContentProcessDidTerminate , 注意: WKWebView内存可能占用过多了");
}
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    ///如果外部没有设置标题,才通过JS从网页获取标题
    //    if (!self.navigationItem.title) {
    //        ///执行JS获取标题
    //        [webView evaluateJavaScript:@"document.title" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
    //            if (!error) {
    //                self.navigationItem.title = response;
    //            }
    //
    //        }];
    //    }
}

#pragma mark- WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    for (JavaScriptAction *action in self.methods) {
        if ([action.name isEqualToString:message.name] && action.handler) {
            action.handler(message);
        }
    }
}
#pragma mark KVO的监听代理
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    //加载进度值
    if ([keyPath isEqualToString:@"estimatedProgress"])
    {
        if (object == self.webView)
        {
            [self.progress setAlpha:1.0f];
            [self.progress setProgress:self.webView.estimatedProgress animated:YES];
            if(self.webView.estimatedProgress >= 1.0f)
            {
                [UIView animateWithDuration:0.5f
                                      delay:0.3f
                                    options:UIViewAnimationOptionCurveEaseOut
                                 animations:^{
                                     [self.progress setAlpha:0.0f];
                                 }
                                 completion:^(BOOL finished) {
                                     [self.progress setProgress:0.0f animated:NO];
                                 }];
            }
        }
        else
        {
            [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
        }
    }
    else if ([keyPath isEqualToString:@"title"]){
        if (object == self.webView) {
            self.navigationItem.title = self.webView.title;
        }else{
            [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
        }
    }
    else
    {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

#pragma mark 移除观察者
- (void)dealloc
{
    [self.webView removeObserver:self forKeyPath:@"estimatedProgress"];
    [self.webView removeObserver:self forKeyPath:@"title"];
}
@end

///JS交互动作封装
@interface JavaScriptAction()
@property (nonatomic , strong)NSString *name;
@property (nonatomic , copy)Handler handler;
@end
@implementation JavaScriptAction

+ (instancetype)actionWithName:(NSString *)name handler:(Handler)handler
{
    return [[JavaScriptAction alloc]initWithName:name handler:handler];
}
- (instancetype)initWithName:(NSString *)name handler:(Handler)handler
{
    self = [super init];
    if (self) {
        self.name = name;
        self.handler = handler;
    }
    return self;
}
@end

@implementation WeakScriptMessageDelegate

- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate{
    self = [super init];
    if (self) {
        _scriptDelegate = scriptDelegate;
    }
    return self;
}

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    [self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];
}

@end
